import { SpriteFrame } from "cc";
import { UserInfo } from "../common/UserInfo";
import { EventManager } from "../event/EventManager";
import { EventType, HeroList, SoldierType, TrainLocation, buildingType, raceType, sProperty, sStudy, soldierConfig, techDescList } from "../settings/const";
import { Advanced, UpGradeType } from "./Advanced";
import { Building, DiamondConsume } from "./Buildings";
import { Events } from "./Events";
import { Hero } from "./Hero";
import ResManager from "../common/ResManager";
import { BManager } from "./BManager";


/**建筑要求 */
interface BuildingRequire {
    id: number,
    name: string,
    level: number,
    isLack?: boolean
}

/**研发的状态 */
export enum DevelopState {
    None,
    Developing,
    Developed
}

/**兵种训练的位置 */
export enum LocationType {
    Barracks = 0,
    Stable = 1,
    Palace = 2,
    Workshop = 3,
}

/**属性的下标 */
export enum SoldierProIndex {
    StepAttack = 0,
    RideAttack = 1,
    StepDefense = 2,
    RideDefense = 3,
    Consume = 4,
    Speed = 5,
    Transport = 6,
    Time = 7,
    Wood = 8,
    Mud = 9,
    Iron = 10,
    Food = 11,
}

export enum SoldierStudyIndex {
    Wood = 1,
    Mud = 2,
    Iron = 3,
    Food = 4,
    Time = 5,
}

/**士兵对象 */
export class Soldier {
    id: number;
    /**名称 */
    name: string;
    /**介绍 */
    desc: string;
    /**数量 */
    count: number;
    /**出征时的数量 */
    armyCount: number = 0;
    /**攻击等级 */
    attackLevel: number = 0;
    /**防御等级 */
    defenseLevel: number = 0;
    /**建造时，需要的木材 */
    wood: number;
    /**建造时，需要的石矿 */
    mud: number;
    /**建造时，需要的铁矿 */
    iron: number;
    /**建造时，需要的粮食 */
    food: number;
    /**步攻 */
    stepAttack: number;
    /**步防 */
    stepDefense: number;
    /**骑攻 */
    rideAttack: number;
    /**骑防 */
    rideDefense: number;
    /**消耗量 */
    consume: number;
    /**速度 */
    speed: number;
    /**运载 */
    transport: number;
    /**建造时间 */
    time: number;
    /**是否被研发过了 */
    developed: DevelopState;

    /**研发需要的木材 */
    studyWood: number;
    /**研发需要的土矿 */
    studyMud: number;
    /**研发需要的铁矿 */
    studyIron: number;
    /**研发需要的粮食 */
    studyFood: number;
    /**研发需要的时间 */
    studyTime: number;

    /**
     * 获取所有兵种，最大的属性
     * @param index 
     * @returns 
     */
    static getMaxProperty(index: SoldierProIndex): number {
        let count = 0
        for (let list of sProperty) {
            if (list[index] > count) {
                count = list[index]
            }
        }
        return count
    }

    /**虚拟出一个所有属性都是最大的兵种 */
    static createMaxSoldier(): Soldier {
        let s = new Soldier()
        s.stepAttack = Soldier.getMaxProperty(SoldierProIndex.StepAttack)
        s.rideAttack = Soldier.getMaxProperty(SoldierProIndex.RideAttack)
        s.stepDefense = Soldier.getMaxProperty(SoldierProIndex.StepDefense)
        s.rideDefense = Soldier.getMaxProperty(SoldierProIndex.RideDefense)
        s.consume = Soldier.getMaxProperty(SoldierProIndex.Consume)
        s.speed = Soldier.getMaxProperty(SoldierProIndex.Speed)
        s.transport = Soldier.getMaxProperty(SoldierProIndex.Transport)
        s.time = Soldier.getMaxProperty(SoldierProIndex.Time)
        s.wood = Soldier.getMaxProperty(SoldierProIndex.Wood)
        s.mud = Soldier.getMaxProperty(SoldierProIndex.Mud)
        s.iron = Soldier.getMaxProperty(SoldierProIndex.Iron)
        s.food = Soldier.getMaxProperty(SoldierProIndex.Food)
        return s
    }

    /**根据 id 来创建一个士兵的对象 */
    static createById(id: number): Soldier {
        let s: Soldier = new Soldier()
        s.id = id
        s.name = soldierConfig[id][0] as string
        s.desc = (soldierConfig[id][1] as string).replace(/<[^>]+>/g, '')
        s.desc = s.desc.split('建造地点')[0]

        //步攻	骑攻	步防	骑防	耗量	速度	运载	建造时间 建造所需资源(木泥铁粮)
        s.stepAttack = sProperty[id][SoldierProIndex.StepAttack]
        s.rideAttack = sProperty[id][SoldierProIndex.RideAttack]
        s.stepDefense = sProperty[id][SoldierProIndex.StepDefense]
        s.rideDefense = sProperty[id][SoldierProIndex.RideDefense]
        s.consume = sProperty[id][SoldierProIndex.Consume]
        s.speed = sProperty[id][SoldierProIndex.Speed]
        s.transport = sProperty[id][SoldierProIndex.Transport]
        s.time = sProperty[id][SoldierProIndex.Time]
        s.wood = sProperty[id][SoldierProIndex.Wood]
        s.mud = sProperty[id][SoldierProIndex.Mud]
        s.iron = sProperty[id][SoldierProIndex.Iron]
        s.food = sProperty[id][SoldierProIndex.Food]

        if (sStudy[id]) {
            s.studyFood = sStudy[id][SoldierStudyIndex.Food]
            s.studyWood = sStudy[id][SoldierStudyIndex.Wood]
            s.studyMud = sStudy[id][SoldierStudyIndex.Mud]
            s.studyIron = sStudy[id][SoldierStudyIndex.Iron]
            s.studyTime = sStudy[id][SoldierStudyIndex.Time]
        }

        return s
    }

    /**通过 soldiersString 创建士兵列表 */
    static createBySoldiersString(): Soldier[] {
        let soldiersString = UserInfo.instance.villageData.soldiersString;
        let studyString = UserInfo.instance.villageData.studyString; 
        
        let soldierList = [];
        if (!soldiersString) {
            return soldierList;
        }
       
        let list = soldiersString.split(';')
        for (let i = 0; i < list.length; i++) {
            let item = list[i];
            let arr = item.split(',');
            let id = parseInt(arr[0]);
            let count = parseInt(arr[1]);


            let s: Soldier = Soldier.createById(id);
            s.count = count;
            if(studyString[s.id]){
                s.attackLevel = studyString[s.id]
                s.defenseLevel = studyString[s.id]
            } else {
                s.attackLevel = 0
                s.defenseLevel = 0
            }
            
            soldierList.push(s);
        }

        return soldierList;
    }

    /**根据index（从零开始算） 获得士兵 */
    static getSoldierByIndex(index:number):Soldier{
        return this.createBySoldiersString()[index]
    }

    /**
     * 通过 StudyString 创建士兵列表
     * @returns 
     */
    static createByStudyString(): Soldier[] {
        
        let studyString = UserInfo.instance.villageData.studyString;
        if(typeof studyString == 'string') {
            studyString = JSON.parse(studyString);
        }

        let soldierList = Soldier.createBySoldiersString();
        for(let so of soldierList){
            if(studyString[so.id]){
                so.developed = DevelopState.Developed
            } else {
                if (so.getDevelopingEvent()) {
                    so.developed = DevelopState.Developing
                } else {
                    so.developed = DevelopState.None
                }
            }
        }
       
        return soldierList
    }

    static createByLocation(location: LocationType): Soldier[] {
        let list = Soldier.createByStudyString()

        return list

        return list.filter((so) => {
            return TrainLocation[so.id] == location
        })

    }

    /**获取兵种在兵种列表的第几个，从零开始算 */
    get soldierIndex(): number {
        let index = 0
        let soldierList = Soldier.createBySoldiersString()
        for (let i = 0; i < soldierList.length; i++) {
            if (this.id == soldierList[i].id) {
                index = i
            }
        }

        return index
    }

    /**是否是侦察类型的兵种 */
    get isScout(): boolean {
        let index = this.soldierIndex
        let scout: number
        if (UserInfo.instance.race == raceType.Rome) {
            scout = 3
        }
        if (UserInfo.instance.race == raceType.Teuton) {
            scout = 3
        }
        if (UserInfo.instance.race == raceType.Gaul) {
            scout = 2
        }

        return index == scout
    }

    /**
     * 获取头像
     * @returns 
     */
    async getHeadImg():Promise<SpriteFrame>{
       
        let sf = await ResManager.instance.loadAssetByUrl<SpriteFrame>(`soliderImg/${this.id}/spriteFrame`)
      
        return sf
    }

    /**
     * 获取升级"进攻等级"所需要的资源和时间
     * @returns 
     */
    getAttackAdvanced(): Advanced {
        // 研究院
        let building: Building
        let bList = UserInfo.instance.bList
        for (let b of bList) {
            if (b.gid == buildingType.B22_Academy) {
                building = Building.createBuildingByBManager(b)
            }
        }

        if (!building) {
            building = Building.createById(buildingType.B22_Academy)
            building.level = 0
        }

        return Advanced.createBySoldierAndLevel(this, this.attackLevel, UpGradeType.Attack, building)
    }
    /**
     * 获取升级“防御等级”所需要的资源和时间
     * @returns 
     */
    getDefenseAdvanced(): Advanced {
        //军械库
        let building: Building
        let bList = UserInfo.instance.bList
        for (let b of bList) {
            if (b.gid == buildingType.B13_Armoury) {
                building = Building.createBuildingByBManager(b)
            }
        }
        
        if (!building) {
            building = Building.createById(buildingType.B13_Armoury)
            building.level = 0
        }

        return Advanced.createBySoldierAndLevel(this, this.defenseLevel, UpGradeType.Defense, building)
    }
    /**
     * 
     */
    getRequireBuilding(): BuildingRequire[] {
        let list: BuildingRequire[] = []
        let buildings = UserInfo.instance.bList
        let tech = techDescList[this.id]
        for (let con of tech.condition) {
            if(con.type == 'b') {
                let id = con.id;
                let level = con.lv;
                let building = Building.createById(parseInt(id))
    
                let tempBuild: BManager
                for (let b of buildings) {
                    if (b.gid == parseInt(id)) {
                        tempBuild = b
                    }
                }
    
                if (!tempBuild || tempBuild.grade < level) {
                    list.push({
                        id: parseInt(id),
                        name: building.name,
                        level: level,
                        isLack: true
                    })
                } else {
                    list.push({
                        id: parseInt(id),
                        name: building.name,
                        level: level,
    
                    })
                }
            }
        }

        return list
    }
    /**研发资源是否足够 */
    get isResEnough(): boolean {
        let villageData = UserInfo.instance.villageData
        let food = villageData.res.food_reserve
        let iron = villageData.res.iron_reserve
        let wood = villageData.res.wood_reserve
        let mud = villageData.res.mud_reserve

        if (food < this.studyFood) {
            return false
        }
        if (iron < this.studyIron) {
            return false
        }
        if (wood < this.studyWood) {
            return false
        }
        if (mud < this.studyMud) {
            return false
        }
        return true
    }

    /**是否能够研发 */
    get isCanDevelop(): boolean {
        let list = this.getRequireBuilding()

        for (let item of list) {
            if (item.isLack) {
                return false
            }
        }

        return this.isResEnough
    }

    /**获取研发新兵种的事件 */
    getDevelopingEvent(): Events {
        let eventList = UserInfo.instance.eventList

        for (let e of eventList) {
            if (e.eType == EventType.study && e.eParam == this.id + '') {
                return e
            }
        }

        return null
    }

    /**研发新兵种的倒计时完成了 ，修改本地数据，并刷新页面*/
    developComplete() {
        let event = this.getDevelopingEvent()
        UserInfo.instance.removeEvent(event)

        let studyString = UserInfo.instance.villageData.studyString
        if(typeof studyString == 'string') {
            studyString = JSON.parse(studyString);
        }

        if(!studyString[this.id]) {
            studyString[this.id] = 1;
        } else {
            studyString[this.id] += 1;
        }

        this.developed = DevelopState.Developed

        UserInfo.instance.villageData.studyString = studyString;
        EventManager.instance.emit(EventManager.EventType.DevelopComplete, this)
    }

    /**
     * 根据当前的资源，能建造多少个兵
     * @returns 
     */
    canCreateHowMany(): number {
        let villageData = UserInfo.instance.villageData
        
        let food = villageData.res.food_reserve
        let iron = villageData.res.iron_reserve
        let wood = villageData.res.wood_reserve
        let mud = villageData.res.mud_reserve

        let foodCount = Math.floor(food / this.food)
        let ironCount = Math.floor(iron / this.iron)
        let woodCount = Math.floor(wood / this.wood)
        let mudCount = Math.floor(mud / this.mud)

        // 如果是领主兵种的情况下
        if(this.soldierIndex == 8){
            let T10Count = Math.floor(this.canCreateHowManyT10() / 3) 
            return Math.min(foodCount, ironCount, woodCount, mudCount, T10Count)
        }

        // 如果是开拓者的情况下
        if (this.soldierIndex == 9) {
            let T10Count = this.canCreateHowManyT10()
            return Math.min(foodCount, ironCount, woodCount, mudCount, T10Count)

        }

        return Math.min(foodCount, ironCount, woodCount, mudCount)
    }

    /**能建造多少个开拓者（t10类型的兵）*/
    canCreateHowManyT10(): number {
        let count = 0
        let building = UserInfo.instance.getBManageById(buildingType.B26_Palace)
        if (building) {
            let grade = building.grade
            if (grade >= 10) {
                count = 3
            }
            if (grade >= 15) {
                count = 6
            }
            if (grade >= 20) {
                count = 9
            }
        } 
        
        building = UserInfo.instance.getBManageById(buildingType.B25_Residence)
        if (building){
            let grade = building.grade

            if (grade >= 10) {
                count = 3
            }
            if (grade >= 20) {
                count = 6
            }
        }
        
        let subLength = UserInfo.instance.villageData.subVillageList.length
        count = count - subLength * 3
        
        count = count - this.count
        count = count - Soldier.getSoldierByIndex(8).count * 3

        if (count < 0) {
            count = 0
        }
        return count
    }

    /**获取训练兵的事件 */
    getTrainEvent(): Events {
        let eventList = UserInfo.instance.eventList
        for (let e of eventList) {
            let arr = e.eParam.split(',')
            let id = arr[0]
            if (e.eType == EventType.train && id == this.id + '') {
                return e
            }
        }
        return null
    }

    /**获取所有训练兵的事件 */
    static getAllTrainEvent(): Events[]{
        let list = []
        let eventList = UserInfo.instance.eventList
        for (let e of eventList) {
            if (e.eType == EventType.train) {
                list.push(e)
            }
        }

        return list
    }

    /**获取宫殿中训练兵的事件 */
    static getPalaceTrainEvent(): Events[]{
        let list = this.getAllTrainEvent()
        return list.filter((e) => {
            let arr = e.eParam.split(',')
            let id = parseInt(arr[0]) 
            return TrainLocation[id] == LocationType.Palace
        })
        
    }

    /**获取兵营中训练兵的事件 */
    static getBarracksTrainEvent(): Events[]{
        let list = this.getAllTrainEvent()
        return list.filter((e) => {
            let arr = e.eParam.split(',')
            let id = parseInt(arr[0]) 
            return TrainLocation[id] == LocationType.Barracks
        })
        
    }

    /**获取士兵训练的时间 */
    get trainTime():number{
        let b = BManager.getBManageById(buildingType.B19_Barracks)
        if(this.soldierIndex >= 8){
            b = BManager.getBManageById(buildingType.B25_Residence)
            if(!b){
                b = BManager.getBManageById(buildingType.B26_Palace)
            }
        }

        if(!b){
            b = new BManager()
        }

        let time = (this.time * Math.pow(0.964, b.grade)) / UserInfo.instance.speed

        return Math.floor(time)
    
    }
}


